package com.daxiang.service;

import com.alibaba.fastjson.JSON;
import com.daxiang.core.JavaCompiler;
import com.daxiang.core.testng.TestNGCodeConvertException;
import com.daxiang.core.testng.TestNGCodeConverterFactory;
import com.daxiang.core.testng.TestNGRunner;
import com.daxiang.model.Response;
import com.daxiang.model.action.Step;
import com.daxiang.model.devicetesttask.DeviceTestTask;
import com.daxiang.model.devicetesttask.Testcase;
import com.daxiang.model.request.ActionDebugRequest;
import com.daxiang.utils.UUIDUtil;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by jiangyitao.
 */
@Slf4j
@Service
public class ActionService {

    public Response debug(ActionDebugRequest request) {
        DeviceTestTask deviceTestTask = new DeviceTestTask();
        BeanUtils.copyProperties(request, deviceTestTask);

        Testcase testcase = new Testcase();
        BeanUtils.copyProperties(request.getAction(), testcase);
        deviceTestTask.setTestcases(Collections.singletonList(testcase));
        escapeDeviceTestTask(deviceTestTask);

        String className = "Debug_" + UUIDUtil.getUUID();
        String code;
        try {
            code = TestNGCodeConverterFactory.create(deviceTestTask.getPlatform()).convert(deviceTestTask, className);
        } catch (TestNGCodeConvertException e) {
            log.error("[{}]转换代码失败", request.getDeviceId(), e);
            return Response.fail(e.getMessage());
        }

        try {
            Class clazz = JavaCompiler.compile(className, code);
            String printInfo = TestNGRunner.debugAction(clazz);
            return Response.success(printInfo, ImmutableMap.of("code", code));
        } catch (Exception e) {
            log.error("[{}]err msg: {}, code: {} ", request.getDeviceId(), e.getMessage(), code);
            return Response.fail(e.getMessage(), ImmutableMap.of("code", code));
        }
    }

    public void escapeDeviceTestTask(DeviceTestTask task) {
        List<Testcase> testcases = task.getTestcases();
        if (CollectionUtils.isEmpty(testcases)) {
            return;
        }
        // 转义Testcase中Step、SetUp、TearDown的参数值
        testcases.forEach(testcase -> {
            escapeSteps(testcase.getSteps());
            escapeSteps(testcase.getSetUp());
            escapeSteps(testcase.getTearDown());
        });
    }

    private void escapeSteps(List<Step> steps) {
        if (null == steps || CollectionUtils.isEmpty(steps)) {
            return;
        }
        steps.forEach(step -> {
            List<String> args = step.getArgs();
            List<String> escapeArgs = args.stream()
                    .map(this::escapeStr)
                    .collect(Collectors.toList());
            step.setArgs(escapeArgs);

            // 递归处理Step.Action的steps
            escapeSteps(step.getAction().getSteps());
        });
    }

    private String escapeStr(String str) {
        if (!needEscape(str)) {
            return str;
        }
        String s = JSON.toJSONString(str);
        // \n字符串替换成换行符
        s = s.replace("\\n", "\n");
        // 去除前后双引号
        return s.substring(1, s.length() - 1);
    }

    /**
     * 判断是否需要转义
     * @param s 原始字符串
     * @return 如果是xpath字符串，则需要转义
     */
    private boolean needEscape(String s) {
        return s.startsWith("/");
    }

}
